/*
 * Copyright 2017 yetao &lt;yetao_ustc@163.com&gt;.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package date.yetao.maven.all.mybatis;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import date.yetao.maven.all.mybatis.dto.ClassInfoDto;
import date.yetao.maven.all.util.LogUtils;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.TopLevelClass;

import java.io.File;
import java.util.List;
import java.util.Properties;

/**
 * <P>为字段增加注解，根据validateConf.json文件添加注解</P>
 * <P>属性logLevel：日志级别</P>
 *
 * @author yetao &lt;yetao_ustc@163.com&gt;
 */
public class AddFieldAnnotationPlugin extends PluginAdapter {

    /**
     * 附加的配置的类的相关信息
     */
    private List<ClassInfoDto> classList = null;

    public AddFieldAnnotationPlugin() {
        super();
    }

    @Override
    public boolean validate(List<String> warnings) {
        // this plugin is always valid
        return true;
    }

    @Override
    public void setProperties(Properties properties) {
        super.setProperties(properties);
        // 加载配置文件
        String logLevel = (String) properties.get("logLevel");
        if (logLevel != null) {
            switch (logLevel.toLowerCase()) {
                case "debug":
                    LogUtils.setLevel(LogUtils.LEVEL_DEBUG);
                    break;
                case "info":
                    LogUtils.setLevel(LogUtils.LEVEL_INFO);
                    break;
                case "warn":
                    LogUtils.setLevel(LogUtils.LEVEL_WARN);
                    break;
                case "error":
                    LogUtils.setLevel(LogUtils.LEVEL_ERROR);
                    break;
            }
        }
        loadConfigFile(properties);
    }

    /**
     * 加载配置文件
     *
     * @param properties
     */
    private void loadConfigFile(Properties properties) {
        // 直接在项目目录下处理文件，以免配置文件被打包
        try {
            File confFile = new File("src/main/java/validateConf.json");
            if (!confFile.exists()) {
                LogUtils.warn("config file does not exist:" + confFile.getCanonicalPath());
                return;
            }
            LogUtils.debug("load config file:" + confFile.getCanonicalPath());
            ObjectMapper mapper = new ObjectMapper();
            classList = mapper.readValue(confFile, new TypeReference<List<ClassInfoDto>>() {
            });
        } catch (Exception ex) {
            LogUtils.error(ex.getMessage());
            ex.printStackTrace();
        }
    }

    @Override
    public boolean modelFieldGenerated(Field field, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
        if (classList == null) {
            return true;
        }
        // 逐个属性进行匹配处理
        String className = topLevelClass.getType().getFullyQualifiedName();
        LogUtils.debug(String.format("className[%s] and fieldName[%s]", className, field.getName()));
        for (ClassInfoDto ci : classList) {
            if (ci.getClassName().equals(className) && ci.getFieldList() != null) {
                for (ClassInfoDto.FieldInfoDto fi : ci.getFieldList()) {
                    if (fi.getFieldName().equals(field.getName())) {
                        // 添加注解
                        if (fi.getAnnotations() != null && !fi.getAnnotations().isEmpty()) {
                            for (String ann : fi.getAnnotations()) {
                                field.addAnnotation(ann);
                            }
                        }
                        break;
                    }
                }
                break;
            }
        }
        return true;
    }
}
